#include "monitor_platform_iot.h"
#include "systemdata.h"
#include <stdlib.h>
#include <stdio.h>
#include "BatMonitor.h"
#include "drv_usart1.h"
#include "bat_afe.h"
#include "powermanage.h"

static uint8_t sendData[1024] = {0};
static uint8_t batNum = 0;
static uint8_t curCaliEnableFlag = 1;

static uint16_t checkdate(uint8_t *buffer, uint16_t len){
    uint16_t  crcvalue = 0;
    for (uint16_t i = 0; i < len; i++){
        crcvalue = crcvalue + buffer[i];
    }
    return crcvalue;
}

static void sket_send_data(uint8_t *data,uint16_t len,uint8_t comNum){
	if(comNum == 1){
		usart1_send(data,len);
	}else if(comNum == 2){
		usart2_send(data,len);
	}else if(comNum == 4){
		usart4_send(data,len);
	}
    // printf("sket iot send:");
	// for(uint16_t i = 0;i<len;i++){
	// 	printf("%02x ",data[i]);
	// }
	// printf("\n");
}

//常规温度转换为平台格式
static uint16_t generalTemp2IotTemp(int8_t temp){
    uint16_t iotTemp = 0;
    if(temp >= 0){
        if(temp > 100){
            iotTemp = 100;
        }else{
            iotTemp = temp;
        }
    }else{
        if(temp < -40){
            iotTemp = 140;
        }else{
            iotTemp = abs(temp) + 100;
        }	
    }

    return iotTemp;
}

//查询单个参数，并将参数赋给data，同时返回参数长度。对于只写的参数，返回0
static uint16_t sket_get_param_buf(uint8_t *data,uint16_t paramFlag,SKET_Read_Type readType) {
    SysRunData_t *runinfo = getSysRunData();
	SysConfData_t *confInfo = getSysConfData();
    uint16_t paramLen = 0;
    uint8_t index = 0;
    switch (paramFlag) {
        case 0x79:{//单体电压
            data[index++] = paramFlag&0xff;
            if(sket_read_single_param == readType){ 
                for(uint8_t i = 0;i<confInfo->fctData.batNum;i++){
                    data[index++] = i + 1;
                    data[index++] = (runinfo->batVol[i] >> 8) & 0xff;
                    data[index++] = (runinfo->batVol[i] >> 0) & 0xff;
                }
                paramLen = 3*confInfo->fctData.batNum + 1;
            }else if(sket_read_all_param == readType){
                data[index++] = (3*confInfo->fctData.batNum)&0xff;
                for(uint8_t i = 0;i<confInfo->fctData.batNum;i++){
                    data[index++] = i + 1;
                    data[index++] = (runinfo->batVol[i] >> 8) & 0xff;
                    data[index++] = (runinfo->batVol[i] >> 0) & 0xff;
                }
                paramLen = 3*confInfo->fctData.batNum + 2;
            }
        }break;
        case 0x80:{//功率管温度（2Byte）
            uint16_t temp = generalTemp2IotTemp(runinfo->mosTemp);
            data[index++] = paramFlag&0xff;
            data[index++] = (temp >> 8) & 0xff;
            data[index++] = (temp >> 0) & 0xff;
            paramLen = 3;
        }break;
        case 0x81:{//电池箱内温度（2Byte）
            uint16_t temp = generalTemp2IotTemp(runinfo->envTemp);
            data[index++] = paramFlag&0xff;
            data[index++] = (temp >> 8) & 0xff;
            data[index++] = (temp >> 0) & 0xff;
            paramLen = 3;
        }break;
        case 0x82:{//电池温度（2Byte）
            uint16_t temp = generalTemp2IotTemp(runinfo->tempOne);
            data[index++] = paramFlag&0xff;
            data[index++] = (temp >> 8) & 0xff;
            data[index++] = (temp >> 0) & 0xff;
            paramLen = 3;
        }break;
        case 0x83:{//电池总电压（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = ((runinfo->packVol*10) >> 8) & 0xff;
            data[index++] = ((runinfo->packVol*10) >> 0) & 0xff;
            paramLen = 3;
        }break;
        case 0x84:{//充放电流（2Byte）
            data[index++] = paramFlag&0xff;
            if(abs(runinfo->batCur) >= 100){
                data[index++] = (uint8_t)((10000 - (runinfo->batCur/10))>>8);
                data[index++] = (uint8_t)((10000 - (runinfo->batCur/10)));
            }else{
                data[index++] = (uint8_t)((10000)>>8);
                data[index++] = (uint8_t)((10000));
            }
            paramLen = 3;
        }break;
        case 0x85:{//SOC（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (runinfo->batSoc) & 0xff;
            paramLen = 2;
        }break;
        case 0x86:{//电池温度传感器数量（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (2) & 0xff;
            paramLen = 2;
        }break;
        case 0x87:{//循环次数（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->fctData.cycleTimes.value >> 8) & 0xff;
            data[index++] = (confInfo->fctData.cycleTimes.value >> 0) & 0xff;
            paramLen = 3;
        }break;
        case 0x89:{//电池健康状态（4Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = 0;
            data[index++] = 0;
            data[index++] = (uint8_t)((runinfo->batSoh) >>8);
            data[index++] = (uint8_t)(runinfo->batSoh);
            paramLen = 5;
        }break;
        case 0x8a:{//电池串数（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->fctData.batNum >> 8) & 0xff;
            data[index++] = (confInfo->fctData.batNum >> 0) & 0xff;
            paramLen = 3;
        }break;
        case 0x8b:{//电池告警信息（2Byte）
            data[index++] = paramFlag&0xff;
            Sket_Warn_Bits warnByte = {.value = 0};
            warnByte.bit.SocLow = runinfo->volWarnByte.volWarn.bit.socLowWarn;
            warnByte.bit.MosTempHigh = runinfo->tempProtByte.bit.mosTempHgProt;
            warnByte.bit.ChgVolHigh = runinfo->volProtByte.volProt.bit.packVolHgProt;
            warnByte.bit.DsgVolLow = runinfo->volProtByte.volProt.bit.packVolLowProt;
            warnByte.bit.BatTempHigh = runinfo->tempProtByte.bit.chgTempHgProt | runinfo->tempProtByte.bit.disTempHgProt;
            warnByte.bit.ChangeCurr = runinfo->curProtByte.bit.chgCUr1Prot | runinfo->curProtByte.bit.chgCur2Prot | runinfo->curProtByte.bit.chgCur3Prot;
            warnByte.bit.DisChaCurr = runinfo->curProtByte.bit.disCur1Prot | runinfo->curProtByte.bit.disCur2Prot | runinfo->curProtByte.bit.disCur3Prot | runinfo->curProtByte.bit.disCur4Prot;
            warnByte.bit.CellVolDiffHigh = runinfo->volProtByte.volProt.bit.cellVolDiffProt;
            warnByte.bit.BoxTempHigh = runinfo->tempProtByte.bit.envTempHgProt;
            warnByte.bit.BatTempLow = runinfo->tempProtByte.bit.chgTempLowProt | runinfo->tempProtByte.bit.disTempLowProt;;
            warnByte.bit.CellVolHigh = (bool)runinfo->volProtByte.cellHgVolProt;
            warnByte.bit.CellVolLow = (bool)runinfo->volProtByte.cellLowVolProt;
            warnByte.bit.A_309 = 0;
            warnByte.bit.B_309 = 0;
            warnByte.bit.humiHigh = 0;
            warnByte.bit.rmBit = 0;

            data[index++] = (warnByte.value >> 8) & 0xff;
            data[index++] = (warnByte.value >> 0) & 0xff;
            paramLen = 3;
        }break;
        case 0x8c:{//电池状态信息（2Byte）
            data[index++] = paramFlag&0xff;
            Sket_State_Bits statebyte = {.value = 0};
            statebyte.bit.chgMos = runinfo->sysSwState.bits.SW_CHG;
            statebyte.bit.dsgMos = runinfo->sysSwState.bits.SW_DSG;
            statebyte.bit.balSW = runinfo->funcSwState.bits.SW_BL_EN;
            statebyte.bit.lossCell = 1;
            statebyte.bit.chgMosErr = 0;
            statebyte.bit.dsgMosErr = 0;
            data[index++] = (statebyte.value >> 8) & 0xff;
            data[index++] = (statebyte.value >> 0) & 0xff;
            paramLen = 3;
        }break;
        case 0x8e: {//总电压过压保护（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = ((confInfo->errorData.packVolHigh.value*10) >> 8) & 0xff;
            data[index++] = ((confInfo->errorData.packVolHigh.value*10) ) & 0xff;
            paramLen = 3;
        }break;
        case 0x8f: {//总电压欠压保护（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = ((confInfo->errorData.packVolLow.value*10) >> 8) & 0xff;
            data[index++] = ((confInfo->errorData.packVolLow.value*10)) & 0xff;
            paramLen = 3;
        }break;
        case 0X90: {//单体过压保护电压（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.batVolHigh.value >> 8) & 0xff;
            data[index++] = (confInfo->errorData.batVolHigh.value) & 0xff;
            paramLen = 3;
        }break;
        case 0X91: {//单体过压恢复电压（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.batVolHighRecover.value >> 8) & 0xff;
            data[index++] = (confInfo->errorData.batVolHighRecover.value) & 0xff;
            paramLen = 3;
        }break;
        case 0X92: {//单体过压保护延时（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.batVolHighTime >> 8) & 0xff;
            data[index++] = (confInfo->errorData.batVolHighTime) & 0xff;
            paramLen = 3;
        }break;
        case 0X93: {//单体欠压保护电压（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.batVolLow.value >> 8) & 0xff;
            data[index++] = (confInfo->errorData.batVolLow.value) & 0xff;
            paramLen = 3;
        }break;
        case 0X94: {//单体欠压恢复电压（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.batVolLowRecover.value >> 8) & 0xff;
            data[index++] = (confInfo->errorData.batVolLowRecover.value) & 0xff;
            paramLen = 3;
        }break;
        case 0X95: {//单体欠压保护延时（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.batVolLowTime >> 8) & 0xff;
            data[index++] = (confInfo->errorData.batVolLowTime) & 0xff;
            paramLen = 3;
        }break;
        case 0X96: {//电芯压差保护值（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.batVolDiff.value >> 8) & 0xff;
            data[index++] = (confInfo->errorData.batVolDiff.value) & 0xff;
            paramLen = 3;
        }break;
        case 0X97: {//放电过流保护值（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.dsgOverCurrent.value >> 8) & 0xff;
            data[index++] = (confInfo->errorData.dsgOverCurrent.value) & 0xff;
            paramLen = 3;
        }break;
        case 0X98: {//放电过流延时（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.dsgOverCurrentTime >> 8) & 0xff;
            data[index++] = (confInfo->errorData.dsgOverCurrentTime) & 0xff;
            paramLen = 3;
        }break;
        case 0X99: {//充电过流保护值（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.chgOverCurrent.value  >> 8) & 0xff;
			data[index++] = confInfo->errorData.chgOverCurrent.value & 0xff;
            paramLen = 3;
        }break;
        case 0X9A: {//充电过流延时（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.chgOverCurrentTime  >> 8) & 0xff;
			data[index++] = confInfo->errorData.chgOverCurrentTime & 0xff;
            paramLen = 3;
        }break;
        case 0X9B: {//均衡启动电压（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->balData.openVol.value  >> 8) & 0xff;
			data[index++] = confInfo->balData.openVol.value & 0xff;
            paramLen = 3;
        }break;
        case 0X9C: {//均衡开启压差（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->balData.openDiffVol.value  >> 8) & 0xff;
			data[index++] = confInfo->balData.openDiffVol.value & 0xff;
            paramLen = 3;
        }break;
        case 0X9D: {//主动均衡开关（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (runinfo->funcSwState.bits.SW_BL_EN) & 0xff;
            paramLen = 2;
        }break;
        case 0X9E: {//功率管温度保护值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.mosTempHigh;
            data[index++] = (temp  >> 8) & 0xff;
            data[index++] = temp  & 0xff;
            paramLen = 3;
        }break;
        case 0X9F: {//功率管温度恢复值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.mosTempHighRecover;
            data[index++] = (temp  >> 8) & 0xff;
            data[index++] = temp  & 0xff;
            paramLen = 3;
        }break;
        case 0XA0: {//环境温度保护值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.envTempHigh;
            data[index++] = (temp  >> 8) & 0xff;
            data[index++] = temp  & 0xff;
            paramLen = 3;
        }break;
        case 0XA1: {//环境温度恢复值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.envTempHighRecover;
            data[index++] = (temp  >> 8) & 0xff;
            data[index++] = temp  & 0xff;
            paramLen = 3;
        }break;
        case 0XA2: {//电池温差保护值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.batTempDiff;
            data[index++] = (temp >> 8) & 0xff;
            data[index++] = (temp) & 0xff;
            paramLen = 3;
        }break;
        case 0XA3: {//电池充电高温保护值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.chgTempHigh;
            data[index++] = (temp >> 8) & 0xff;
            data[index++] = (temp) & 0xff;
            paramLen = 3;
        }break;
        case 0XA4: {//电池放电高温保护值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.dsgTempHigh;
            data[index++] = (temp >> 8) & 0xff;
            data[index++] = (temp) & 0xff;
            paramLen = 3;
        }break;
        case 0XA5: {//充电低温保护值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.chgTempLow;
            data[index++] = (temp >> 8) & 0xff;
            data[index++] = (temp) & 0xff;
            paramLen = 3;
        }break;
        case 0XA6: {//充电低温保护恢复值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.chgTempLowRecover;
            data[index++] = (temp  >> 8) & 0xff;
            data[index++] = temp  & 0xff;
            paramLen = 3;
        }break;
        case 0XA7: {//放电低温保护值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.dsgTempLow;
            data[index++] = (temp >> 8) & 0xff;
            data[index++] = (temp) & 0xff;
            paramLen = 3;
        }break;
        case 0XA8: {//放电低温保护恢复值（2Byte）
            data[index++] = paramFlag&0xff;
            int16_t temp = confInfo->errorData.dsgTempLowRecover;
            data[index++] = (temp  >> 8) & 0xff;
            data[index++] = temp  & 0xff;
            paramLen = 3;
        }break;
        case 0XA9: {//电芯串数设置（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->fctData.batNum) & 0xff;
            paramLen = 2;
        }break;
        case 0XAA: {//电池容量设置（4Byte）
            data[index++] = paramFlag&0xff;
            uint32_t normalCap = confInfo->fctData.normalCap.value / 10;
            data[index++] = (normalCap >> 24) & 0xff;
            data[index++] = (normalCap >> 16) & 0xff;
            data[index++] = (normalCap >> 8) & 0xff;
            data[index++] = (normalCap) & 0xff;
            paramLen = 5;
        }break;
        case 0XAB: {//充电MOS管开关（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = runinfo->sysSwState.bits.SW_CHG&0x01;
            paramLen = 2;
        }break;
        case 0XAC: {//放电MOS管开关（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = runinfo->sysSwState.bits.SW_DSG&0x01;
            paramLen = 2;
        }break;
        case 0XAD: {//电流校准（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->caliData.curRadio) & 0xff;//大端传输，在给caliValue赋值时，也采用大端方式
            data[index++] = (confInfo->caliData.curRadio) & 0xff;
            paramLen = 3;
        }break;
         case 0XAE: {//保护板地址（1Byte）
             data[index++] = paramFlag&0xff;
             data[index++] = 0x01 & 0xff;
             paramLen = 2;
         }break;
        case 0XAF: {//电池类型（1Byte）
            data[index++] = paramFlag&0xff;
            if (confInfo->fctData.batType == lstlBat) {//磷酸铁锂
                data[index++] = 0;
            }else if (confInfo->fctData.batType == sanyuanBat) {//三元
                data[index++] = 1;
            }else if (confInfo->fctData.batType == tslBat) {//钛酸锂
                data[index++] = 2;
            }else if(confInfo->fctData.batType == nslBat){
				data[index++] = 3;
			}else {//其它默认为磷酸铁锂
                data[index++] = 0;
            } 
            paramLen = 2;
        }break;
        // case 0XB0: {//休眠等待时间（2Byte）
        //     data[index++] = paramFlag&0xff;
        //     data[index++] = (0 >> 8) & 0xff;
        //     data[index++] = (0) & 0xff;
        //     paramLen = 3;
        // }break;
        case 0XB1: {//低容量报警值（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->warnData.socLow) & 0xff;
            paramLen = 2;
        }break;
        case 0XB2: {//修改参数密码(10Byte)
            data[index++] = paramFlag&0xff;
            paramLen = 11;
        }break;
        case 0XB3: {//专用充电器开关(1Byte)
            data[index++] = paramFlag&0xff;
            data[index++] = 0x01&0xff;
            paramLen = 2;
        }break;
        case 0XB4: {//设备ID码(8Byte)
            data[index++] = paramFlag&0xff;
            for (uint8_t i = 0; i < 8; i++) {
                data[index++] = confInfo->fctData.hdSerial[i];
            }
            paramLen = 9;
        }break;
        case 0XB5: {//出厂日期(4Byte)例如2024.02,表示为:0x32 0x34 0x30 0x32,取出BT码中的年月
            data[index++] = paramFlag&0xff;
            data[index++] = confInfo->fctData.BtNum[15];
            data[index++] = confInfo->fctData.BtNum[16];
            data[index++] = confInfo->fctData.BtNum[17];
            data[index++] = confInfo->fctData.BtNum[18];
            paramLen = 5;
        }break;
        case 0XB6: {//系统工作时间(4Byte),单位：分
            data[index++] = paramFlag&0xff;
            data[index++] = (runinfo->sysRunTime_min >> 24) & 0xff;
            data[index++] = (runinfo->sysRunTime_min >> 16) & 0xff;
            data[index++] = (runinfo->sysRunTime_min >> 8) & 0xff;
            data[index++] = (runinfo->sysRunTime_min) & 0xff;
            paramLen = 5;
        }break;
        case 0XB7: {//软件版本号(15Byte)
            data[index++] = paramFlag&0xff;
            uint8_t *pSovtVersion = (uint8_t *)SOFT_VERSION;
			if(strlen(SOFT_VERSION) < 15){
				for (uint8_t i = 0; i < strlen(SOFT_VERSION); i++) {
						data[index++] = pSovtVersion[i];
				}
			}else{
				for (uint8_t i = 0; i < 15; i++) {
						data[index++] = pSovtVersion[i];
				}
			}									        
            paramLen = 16;
        }break;
        case 0XB8: {//是否启动电流校准（1Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (curCaliEnableFlag) & 0xff;
            paramLen = 2;
        }break;
        case 0XB9: {//电池实际容量设置（4Byte）
            data[index++] = paramFlag&0xff;
            uint32_t realCap = confInfo->fctData.realCap.value / 10;
            data[index++] = (realCap >> 24) & 0xff;
            data[index++] = (realCap >> 16) & 0xff;
            data[index++] = (realCap >> 8) & 0xff;
            data[index++] = (realCap) & 0xff;
            paramLen = 5;
        }break;
        case 0XBA: {//24字节的厂家ID命名（24Byte）
            data[index++] = paramFlag&0xff;
            for (uint8_t i = 0; i < 24; i++) {
                data[index++] = confInfo->fctData.BtNum[i];
            }
			data[index++] = 0x00;
            paramLen = 26;
        }break;
        case 0XBE: {//电 芯 低 压 关 闭 GPS（2Byte）
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->fctData.poweroff_vol.value>>8)&0xff;
            data[index++] = (confInfo->fctData.poweroff_vol.value>>0)&0xff;
            paramLen = 3;
        }break;
         case 0XBF: {//电 芯 低 压 恢 复 GPS（2Byte）
             data[index++] = paramFlag&0xff;
             data[index++] = ((confInfo->fctData.poweroff_vol.value + 100)>>8)&0xff;
             data[index++] = ((confInfo->fctData.poweroff_vol.value + 100)>>0)&0xff;
             paramLen = 3;
         }break;
        case 0XC0: {//是否打开湿度保护功能（1Byte）
             data[index++] = paramFlag&0xff;
             data[index++] = (0) & 0xff;
             paramLen = 2;
         }break;
         case 0XC1: {//当前湿度数值(1Byte)
             data[index++] = paramFlag&0xff;
             data[index++] = (0) & 0xff;
             paramLen = 2;
         }break;
         case 0XC2: {//报警湿度阈值（1Byte）
             data[index++] = paramFlag&0xff;
             data[index++] = (0) & 0xff;
             paramLen = 2;
         }break;
        case 0XC3: {//设定短路电流值（2Byte）单位:1A
            data[index++] = paramFlag&0xff;
			data[index++] = (confInfo->errorData.scdVol.value/10) & 0xff;
            paramLen = 2;
        }break;
        case 0XC4: {//设定短路延时时间（2Byte）单位:1uS，范围:70-400uS
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.scdVolTime.value >> 8) & 0xff;
			data[index++] = confInfo->errorData.scdVolTime.value & 0xff;
            paramLen = 3;
        }break;
         case 0XC5: {//功能开关（2Byte）
             data[index++] = paramFlag&0xff;
             uint16_t funcSwByte = 0;
             funcSwByte |= (0x00 << 0);//bit0:短路功能开关，有效
             funcSwByte |= (0x00 << 1);//bit1:温度功能开关，有效
             funcSwByte |= (0x00 << 2);//bit2:蓝牙重启，无效
             funcSwByte |= (0x00 << 3);//bit3:GPS启用，启用
             funcSwByte |= (0x00 << 4);//bit4:soc校准，不校准
             data[index++] = (funcSwByte>>8)&0xff;
             data[index++] = funcSwByte&0xff;
             paramLen = 3;
         }break;
        case 0XC6: {//放电过流二级保护值（2Byte）单位:1A
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.dsgOverCurrent2.value  >> 8) & 0xff;
			data[index++] = confInfo->errorData.dsgOverCurrent2.value & 0xff;
            paramLen = 3;
        }break;
        case 0XC7: {//放电二级过流延时时间（2Byte）单位:1S，范围:1-16S
            data[index++] = paramFlag&0xff;
            data[index++] = (confInfo->errorData.dsgOverCurrent2Time >> 8) & 0xff;
			data[index++] = confInfo->errorData.dsgOverCurrent2Time & 0xff;
            paramLen = 3;
        }break;
        case 0XC8: {//低容量校准电压（2Byte）,单位:1mV，范围:1000-4500mV
            data[index++] = paramFlag&0xff;
            uint16_t caliVol = 0;
            if(confInfo->fctData.batType == sanyuanBat){
                caliVol = 3123;
            }else if(confInfo->fctData.batType == lstlBat){
                caliVol = 3180;
            }else if(confInfo->fctData.batType == tslBat){
                caliVol = 3123;
            }else if(confInfo->fctData.batType == nslBat){
				caliVol = 2215;
			}
			else{
                caliVol = 3123;
            }
            data[index++] = (caliVol >> 8) & 0xff;
			data[index++] = caliVol & 0xff;
            paramLen = 3;
        }break;
        default: {//如果参数编号不在选项内，返回0
            paramLen = 0;
        }break;
    }
    return paramLen;
}

//读取所有数据
static void sket_send_all_param(uint8_t comNum) {
    uint16_t index = 0;
    uint16_t paramCheckCnt = 0;
    memset(sendData,0,1024);
    sendData[index ++] = ZX_STX_H;
    sendData[index ++] = ZX_STX_L;
    sendData[index ++] = 0x00;//长度H，最后再赋值
    sendData[index ++] = 0x00;//长度L，最后再赋值
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = sket_read_all_param;//命令字
    sendData[index ++] = 0x00;//数据来源:bms
    sendData[index ++] = 0x01;//传输类型:应答帧
    while (paramCheckCnt < 1024) {
        uint16_t len = sket_get_param_buf(&sendData[index], paramCheckCnt,sket_read_all_param);
        if(len > 0){
            index += len;
        }
        paramCheckCnt ++;
    }

    sendData[index ++] = ZX_EOD;

    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;

    sendData[2] = ((index + 2)>>8)&0xff;
    sendData[3] = ((index + 2)>>0)&0xff;

    uint16_t crcvalue = checkdate(sendData,index);
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = (uint8_t)(crcvalue>>8);
    sendData[index ++] = (uint8_t)(crcvalue);

    sket_send_data(sendData,index,comNum);
}

//读取单个数据
static void sket_send_single_param(uint16_t paramFlag,uint8_t comNum) {
    uint16_t index = 0;
    uint16_t paramCheckCnt = 0;
    memset(sendData,0,1024);
    sendData[index ++] = ZX_STX_H;
    sendData[index ++] = ZX_STX_L;
    sendData[index ++] = 0x00;//长度H，最后再赋值
    sendData[index ++] = 0x00;//长度L，最后再赋值
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = sket_read_single_param;//命令字
    sendData[index ++] = 0x00;//数据来源:bms
    sendData[index ++] = 0x01;//传输类型:应答帧
    uint16_t len = sket_get_param_buf(&sendData[index], paramFlag,sket_read_all_param);
    if(len > 0){
        index += len;
    }

    sendData[index ++] = ZX_EOD;

    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;

    sendData[2] = ((index + 2)>>8)&0xff;
    sendData[3] = ((index + 2)>>0)&0xff;

    uint16_t crcvalue = checkdate(sendData,index);
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = (uint8_t)(crcvalue>>8);
    sendData[index ++] = (uint8_t)(crcvalue);

    sket_send_data(sendData,index,comNum);
}

static void sket_set_single_param(uint16_t paramFlag,uint8_t *data,uint16_t comNum){
    SysRunData_t *runinfo = getSysRunData();
	SysConfData_t *confInfo = getSysConfData();
    switch (paramFlag) {
        case 0x8e: {//总电压过压保护（2Byte）
            confInfo->errorData.packVolHigh.value = ((((uint16_t)data[0]) <<8 ) | data[1])/10;
        }break;
        case 0x8f: {//总电压欠压保护（2Byte）
            confInfo->errorData.packVolLow.value = ((((uint16_t)data[0]) <<8 ) | data[1])/10;
        }break;
        case 0X90: {//单体过压保护电压（2Byte）
            confInfo->errorData.batVolHigh.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X91: {//单体过压恢复电压（2Byte）
            confInfo->errorData.batVolHighRecover.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X92: {//单体过压保护延时（2Byte）
            confInfo->errorData.batVolHighTime = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X93: {//单体欠压保护电压（2Byte）
            confInfo->errorData.batVolLow.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X94: {//单体欠压恢复电压（2Byte）
            confInfo->errorData.batVolLowRecover.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X95: {//单体欠压保护延时（2Byte）
            confInfo->errorData.batVolLowTime = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X96: {//电芯压差保护值（2Byte）
            confInfo->errorData.batVolDiff.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X97: {//放电过流保护值（2Byte）
            confInfo->errorData.dsgOverCurrent.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X98: {//放电过流延时（2Byte）
            confInfo->errorData.dsgOverCurrentTime = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X99: {//充电过流保护值（2Byte）
            confInfo->errorData.chgOverCurrent.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
			confInfo->errorData.chgOverCurrent2.value = confInfo->errorData.chgOverCurrent.value*3/2;
			confInfo->errorData.chgOverCurrent3.value = confInfo->errorData.chgOverCurrent2.value*3/2;
			afe_OCC1_Config(confInfo->errorData.chgOverCurrent2.value,confInfo->errorData.chgOverCurrent2Time);
			afe_OCC2_Config(confInfo->errorData.chgOverCurrent3.value,confInfo->errorData.chgOverCurrent3Time,1);
        }break;
        case 0X9A: {//充电过流延时（2Byte）
            confInfo->errorData.chgOverCurrentTime = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X9B: {//均衡启动电压（2Byte）
            confInfo->balData.openVol.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X9C: {//均衡开启压差（2Byte）
            confInfo->balData.openDiffVol.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X9D: {//主动均衡开关（1Byte）
            runinfo->funcSwState.bits.SW_BL_EN = data[0];
        }break;
        case 0X9E: {//功率管温度保护值（2Byte）
            confInfo->errorData.mosTempHigh = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0X9F: {//功率管温度恢复值（2Byte）
            confInfo->errorData.mosTempHighRecover = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA0: {//环境温度保护值（2Byte）
            confInfo->errorData.envTempHigh = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA1: {//环境温度恢复值（2Byte）
            confInfo->errorData.envTempHighRecover = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA2: {//电池温差保护值（2Byte）
            confInfo->errorData.batTempDiff = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA3: {//电池充电高温保护值（2Byte）
            confInfo->errorData.chgTempHigh = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA4: {//电池放电高温保护值（2Byte）
            confInfo->errorData.dsgTempHigh = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA5: {//充电低温保护值（2Byte）
            confInfo->errorData.chgTempLow = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA6: {//充电低温保护恢复值（2Byte）
            confInfo->errorData.chgTempLowRecover = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA7: {//放电低温保护值（2Byte）
            confInfo->errorData.dsgTempLow = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA8: {//放电低温保护恢复值（2Byte）
            confInfo->errorData.dsgTempLowRecover = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XA9: {//电芯串数设置（1Byte）
            confInfo->fctData.batNum = data[0];
            Judge_BatNum();
        }break;
        case 0XAA: {//电池容量设置（4Byte）
            uint16_t value = ((((uint32_t)data[0]) <<24 ) | (((uint32_t)data[1]) <<16 ) | (((uint32_t)data[2]) <<8 ) | data[3]);
            confInfo->fctData.normalCap.value = value*10;
			runinfo->norCap_mAmS = ((uint64_t)confInfo->fctData.normalCap.value) * 360 * 1000 * 1000; // 实际容量初始化
        }break;
        case 0XAB: {//充电MOS管开关（1Byte）
            runinfo->funcSwState.bits.SW_CHG_EN = data[0];
        }break;
        case 0XAC: {//放电MOS管开关（1Byte）
            runinfo->funcSwState.bits.SW_DSG_EN = data[0];
        }break;
        case 0XAD: {//电流校准（2Byte）
            if(curCaliEnableFlag == 1){
                uint16_t stdCurrent = ((((uint16_t)data[0]) <<8 ) | data[1]);
                float caliValue = ((float)(stdCurrent)) / ((float)abs(runinfo->batRawCur));
                if (caliValue >= 0.5 && caliValue <= 1.5){
                    confInfo->caliData.curRadio = (unsigned short)(caliValue * 10000.0);
                }else{
                    
                }
            }else{

            }
        }break;
        case 0XAE: {//保护板地址（1Byte）
            
        }break;
        case 0XAF: {//电池类型（1Byte）
            if(data[0] == 0){//磷酸铁锂
                confInfo->fctData.batType = lstlBat;
            }else if(data[0] == 1){//三元
                confInfo->fctData.batType = sanyuanBat;
            }else if(data[0] == 2){//钛酸锂
                confInfo->fctData.batType = tslBat;
            }else if(data[0] == 3){
				confInfo->fctData.batType = nslBat;
			}else{//其它
                confInfo->fctData.batType = lstlBat;
            }
        }break;
        case 0XB0: {//休眠等待时间（2Byte）
            
        }break;
        case 0XB1: {//低容量报警值（1Byte）
            confInfo->warnData.socLow = data[0];
        }break;
        case 0XB2: {//修改参数密码(10Byte)
            
        }break;
        case 0XB3: {//专用充电器开关(1Byte)
            
        }break;
        case 0XB4: {//设备ID码(8Byte)
            for (uint8_t i = 0; i < 8; i++) {
                confInfo->fctData.hdSerial[i] = data[i];
            }
        }break;
        case 0XB5: {//出厂日期(4Byte)例如2024.02,表示为:0x32 0x34 0x30 0x32,取出BT码中的年月
            printf("Product Time:20");
            for (uint8_t i = 0; i < 4; i++) {
                printf("%c",data[i]);
            }
            printf("\n");
        }break;
        case 0XB6: {//系统工作时间(4Byte),单位：分
            runinfo->sysRunTime_min = ((((uint32_t)data[0]) <<24 ) | (((uint32_t)data[1]) <<16 ) | (((uint32_t)data[2]) <<8 ) | data[3]);
        }break;
        case 0XB8: {//是否启动电流校准（1Byte）
            curCaliEnableFlag = data[0];
        }break;
        case 0XB9: {//电池实际容量设置（4Byte）
            uint16_t value = ((((uint32_t)data[0]) <<24 ) | (((uint32_t)data[1]) <<16 ) | (((uint32_t)data[2]) <<8 ) | data[3]);
            confInfo->fctData.realCap.value = value*10;
			runinfo->realCap_mAms = ((uint64_t)confInfo->fctData.realCap.value) * 360 * 1000 * 1000;  // 实际容量初始化
			runinfo->batSoh = runinfo->realCap_mAms * 100 / runinfo->norCap_mAmS;
        }break;
        case 0XBA: {//24字节的厂家ID命名（24Byte）
            for (uint8_t i = 0; i < 24; i++) {
                confInfo->fctData.BtNum[i] = data[i];
            }
        }break;
        case 0XBB: {//电池休眠
            system_poweroff();
        }break;
        case 0XBC: {//恢复出厂设置
            uint16_t value = data[0];
            printf("[0x%02x]value = %d\n",paramFlag,value);
        }break;
        case 0XBD: {//远程升级标识符
            
        }break;
        case 0XBE: {//电 芯 低 压 关 闭 GPS（2Byte）
            confInfo->fctData.poweroff_vol.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XBF: {//电 芯 低 压 恢 复 GPS（2Byte）
            
        }break;
        case 0XC0: {//是否打开湿度保护功能（1Byte）
            
        }break;
        case 0XC1: {//当前湿度数值(1Byte)
            
        }break;
        case 0XC2: {//报警湿度阈值（1Byte）
            
        }break;
        case 0XC3: {//设定短路电流值（1Byte）单位:10A
            confInfo->errorData.scdVol.value = data[0]*10;
            afe_SCD_Config(confInfo->errorData.scdVol.value,confInfo->errorData.scdVolTime.value,1);
        }break;
        case 0XC4: {//设定短路延时时间（2Byte）单位:1uS，范围:70-400uS
            confInfo->errorData.scdVolTime.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
            afe_SCD_Config(confInfo->errorData.scdVol.value,confInfo->errorData.scdVolTime.value,1);
        }break;
        case 0XC5: {//功能开关（2Byte）
            
        }break;
        case 0XC6: {//放电过流二级保护值（2Byte）单位:1A
            confInfo->errorData.dsgOverCurrent2.value = ((((uint16_t)data[0]) <<8 ) | data[1]);
	        confInfo->errorData.dsgOverCurrent3.value = confInfo->errorData.dsgOverCurrent2.value*3/2;
		    confInfo->errorData.dsgOverCurrent4.value = confInfo->errorData.dsgOverCurrent3.value*3/2;
			afe_OCD1_Config(confInfo->errorData.dsgOverCurrent3.value,confInfo->errorData.dsgOverCurrent3Time);
			afe_OCD2_Config(confInfo->errorData.dsgOverCurrent4.value,confInfo->errorData.dsgOverCurrent4Time.value,1);					
        }break;
        case 0XC7: {//放电二级过流延时时间（2Byte）单位:1S，范围:1-16S
            confInfo->errorData.dsgOverCurrent2Time = ((((uint16_t)data[0]) <<8 ) | data[1]);
        }break;
        case 0XC8: {//低容量校准电压（2Byte）,单位:1mV，范围:1000-4500mV
            
        }break;
        default: {//如果参数编号不在选项内，返回0
            
        }break;
    }
    uint16_t index = 0;
    memset(sendData,0,1024);
    sendData[index ++] = ZX_STX_H;
    sendData[index ++] = ZX_STX_L;
    sendData[index ++] = 0x00;//长度H，最后再赋值
    sendData[index ++] = 0x00;//长度L，最后再赋值
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = 0x00;//BMS终端号
    sendData[index ++] = sket_read_single_param;//命令字
    sendData[index ++] = 0x00;//数据来源:bms
    sendData[index ++] = 0x01;//传输类型:应答帧
    sendData[index ++] = paramFlag;//参数标识

    sendData[index ++] = ZX_EOD;

    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;

    sendData[2] = ((index + 2)>>8)&0xff;
    sendData[3] = ((index + 2)>>0)&0xff;

    uint16_t crcvalue = checkdate(sendData,index);
    sendData[index ++] = 0x00;
    sendData[index ++] = 0x00;
    sendData[index ++] = (uint8_t)(crcvalue>>8);
    sendData[index ++] = (uint8_t)(crcvalue);

    sket_send_data(sendData,index,comNum);

    saveSysConfData();
}

//接收上位机下发的数据进行解析
void sket_recv_data(uint8_t *data, uint16_t len,uint8_t comNum){
    uint16_t dataLen = (len % 1025);
    uint16_t recvLen = 0;
    if (data[0] != ZX_STX_H || data[1] != ZX_STX_L) {
        return;
    }
    recvLen = ((uint16_t)data[2] << 8) | data[3];
    uint16_t crcvalue = checkdate(data, recvLen);
    if (((uint8_t)crcvalue != data[dataLen - 1]) && ((uint8_t)(crcvalue >> 8) == data[dataLen - 2])) {
        printf("Crc check error!\n");
        return;
    }
    
    uint8_t bmsId[4] = { data[4] ,data[5] ,data[6] ,data[7] };
    uint8_t cmd = data[8];
    switch (cmd) {
        case 0x01: {//激活指令的回复
            
        }break;
        case 0x02: {//写入指令的回复
            uint8_t paramFlag = data[11]&0xff;//参数标识
            sket_set_single_param(paramFlag,&data[12],comNum);
        }break;
        case 0x03: {//读指令的回复
            uint8_t paramFlag = data[11]&0xff;
            sket_send_single_param(paramFlag,comNum);
        }break;
        case 0x05: {//对密码
            
        }break;
        case 0x06: {//读取全部数据的回复
            sket_send_all_param(comNum);
        }break;
        default: {//其它数据
            
        }break;
    }
}
